<?php

/**
 * Library :: Pattern :: Registry
 *
 * Basic implementation of the registry pattern, designed to be extended
 * or instanced by classes requiring registry functionality.
 *
 * Warlock is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 *
 * @package    warlock
 * @author     David Cole <neophyte@sourcetutor.com>
 * @license    GNU/GPL v2
 */

class Registry extends Object
{
    var $_registry = array();

    function __construct()
    {
        $this->_registry = array();
    }

    /**
     * Set Registry Value
     *
     * Attempts to set the value of the specified registry key
     *
     * @param  string  $name the name of the elemenet to be set
     * @param  string  $value the value with which the element should be set
     *
     * @return void
     * @access public
     */
    function Set($name, $value)
    {
        /*
         * Get a reference to the point in the registry
         * to which the value is to be added.
         */

        if(strstr($name, '.'))
        {
            $key =  explode('.', $name);
            $ref =& $this->_registry;

            for ($i = 0; $i < count($key); $i++)
            {
                if(!array_key_exists($key[$i], $ref))
                    $ref[$key[$i]] = array();

                $ref =& $ref[$key[$i]];
            }
        }
        else
            $ref = &$this->_registry[$name];

        // Set The Value within the Registry
        switch (true)
        {
            case (!isset($ref))      :
            case (is_scalar($value)) :
            case (is_scalar($ref))   : $ref = $value; break;
            case (is_array($ref))    : $ref = array_merge_recursive($ref, $value);
        }
    }

    /**
     * Get Registry Value
     *
     * Attempts to retrieve the requested registry value.
     *
     * @param  string  $name the name of the elemenet to be retrieved
     * @return mixed   false if the element cant be found, else a reference to the element.
     *
     */
    function &Get($name)
    {
        if(array_key_exists($name, $this->_registry))
        {
            // Element directly specified
            return $this->_registry[$name];
        }
        else
        {
            if(strstr($name, '.'))
            {
                // Requested element is nested within the registry

                $key = explode('.', $name);
                $ref =& $this->_registry;

                for ($i = 0; $i < count($key); $i++)
                {
                    if(array_key_exists($key[$i], $ref))
                    {
                        // Key found, lets progress to the next level
                        $ref =& $ref[$key[$i]];
                    }
                    else
                    {
                        // Nothing found for this level, requested value cant exist
                        return false;
                    }
                }

                // Return the final value
                return $ref;
            }
            else
            {
                return false;
            }
        }
    }

    function GetRegistry()
    {
        return $this->_registry;
    }
}

?>